/*******************************************************************************
 ** Name: usart.cpp                                                           **
 ** Description:              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the license.txt within              **
 ** this distribution or at http://www.munixos.net/licensing.                 **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $HOME/license.txt.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 **                                                                           **
 ** Copyright (c) 2009-2010  Barry Gian James <bjames@munixos.net>            **
 ** All rights reserved.                                                      **
 **                                                                           **
 ** Ref: $HeadURL$
 ******************************************************************************/
// Portions (C) 2011 OpenHouseware, LLC.
// All Rights Reserved

#define _MUNIX_USART_CPP_ID "$Id$"
// Modified $DateTime$ by $Author$

#include "common.h"
#include "usart.h"


USART::USART(uint32 b, uint8 d, uint8 i)
: Bus(i, BusType::SPI, BusMode::Master) {
    baud = b;
    direction = d;
    rxBuff = new RingBuff(DEFAULT_RXBUFF_SZ);
    txBuff = new RingBuff(DEFAULT_TXBUFF_SZ);
}


USART::~USART() {
    if (rxBuff) delete rxBuff;
    if (txBuff) delete txBuff;
}

#if defined(USART_OPERATOR_STREAM)
// Stream Operator members
USART &
USART::operator << (USART & u)
{
    return *this;
}

USART &
USART::operator << (bool b)
{
    if (b)  tx((1+0x30));
    else    tx((0+0x30));
    return *this;
}

USART & endl(USART & u)
{
    u.tx('\r');
    u.tx('\n');
    return u;
}

USART &
USART::operator << (uint8 i)
{
    tx(i);
    return *this;
}
USART &
USART::operator << (uint16 i)
{
    tx(i);
    tx((i>>8));
    return *this;
}
USART &
USART::operator << (char c)
{
    tx(c);
    return *this;
}
USART &
USART::operator << (char * msg)
{
    WriteRAMStr(msg);
    return *this;
}
USART &
USART::operator << (int8_t i)
{
    tx(i);
    return *this;
}
USART &
USART::operator << (int16_t i)
{
     tx(i);
    tx((i>>8));
    return *this;

}
#if defined(USART_STREAM_LONG)
USART &
USART::operator << (int32_t i)
{
    tx(i);
    tx((i>>8));
    tx((i>>16));
    tx((i>>24));
    return *this;
}
USART &
USART::operator << (uint32_t i)
{
    tx(i);
    tx((i>>8));
    tx((i>>16));
    tx((i>>24));
    return *this;

}
#endif
#if defined(USART_STREAM_DOUBLE)
USART &
USART::operator << (float f)
{

}
USART &
USART::operator << (double d)
{

}
#endif

#if defined(USART_OPERATOR_STREAM)
// Operators for implicit type conversion
USART & operator << (USART & out,char c)
{
    out.tx(c);
    return out;
}
USART & operator << (USART &out,signed char c)
{
    out.tx(c);
    return out;
}
USART & operator << (USART &out, const signed char * c)
{
    USART::WriteLine((const char*)c);
    return out;
}
USART & operator << (USART &out, const unsigned char * c)
{
    out.WriteLine((const char*)c);
    return out;
}
#endif
USART & operator << (USART &out, char const __attribute__((__progmem__)) * msg)
{
    out.WriteLine(msg);
    return out;
}
#endif  /* USART_OPERATOR_STREAM */


void
USART::PowerUp() {
    switch (id) {
        case 0:
            power_usart0_enable();
            break;
#if DUAL_USART
        case 1:
            power_usart1_enable();
            break;
#endif
#if XMEGA_DEFINED || defined(__AVR_ATmega1280__) \
	|| defined(__AVR_ATmega2560__)
        case 2:
            power_usart2_enable();
            break;
        case 3:
            power_usart3_enable();
            break;
#endif
        default:
            power_usart0_enable();
            break;
    }
}

void
USART::PowerDown() {
    switch (id) {
        case 0:
            power_usart0_disable();
            break;
#if DUAL_USART
        case 1:
            power_usart1_disable();
            break;
#endif
#if XMEGA_DEFINED
        case 2:
            power_usart2_disable();
            break;
        case 3:
            power_usart3_disable();
            break;
#endif
        default:
            power_usart0_disable();
            break;
    }
}

bool
USART::Connect()
{
    if (direction & USART_RX) UCSR0B |= (1 << RXEN0);
    if (direction & USART_TX) UCSR0B |= (1 << TXEN0);

    uint16 ubrrval = ((F_CPU)/(16*baud) - 1UL);

    UBRR0L = (ubrrval & 0xFF);
    UBRR0H = (ubrrval >>8);

    return true;
}

void
USART::SendWord(uint8 a, wchar_t w) {
    char s = w & 0x00FF;
    tx(s);
    s = w & 0xFF00;
    tx(s);
}

wchar_t
USART::RecvWord() {
    wchar_t ret = rx();
    ret <<= 8;
    ret = rx();
    return ret;
}

